package com.ali.common;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class Rsa2Util {
    private static final String RSA = "RSA";
    private static final String ALGORITHM_SHA256 = "SHA256withRSA";

    /**
     * 获取公钥与私钥
     */
    public static Map<String, String> getKey() {
        Map<String, String> keyMap = new HashMap<>();

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
            keyPairGenerator.initialize(1024, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            //获取公钥
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKey = Base64Util.encrypt(rsaPublicKey.getEncoded());
            keyMap.put("publicKey", publicKey);

            //获取私钥
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            String privateKey = Base64Util.encrypt(rsaPrivateKey.getEncoded());
            keyMap.put("privateKey", privateKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return keyMap;
    }

    /**
     * RSA2私钥签名
     */
    public static String sign(String content, String privateKeyStr) {
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);

        try {
            Signature signature = Signature.getInstance(ALGORITHM_SHA256);
            PrivateKey privateKey = getPrivateKey(privateKeyStr);
            signature.initSign(privateKey);
            signature.update(contentByte);
            byte[] signByte = signature.sign();
            return Base64Util.encrypt(signByte);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取PrivateKey
     */
    private static PrivateKey getPrivateKey(String privateKeyStr) {
        try {
            byte[] privateKeyByte = Base64Util.getByteByDecrypt(privateKeyStr);

            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * RSA2公钥验签
     */
    public static boolean verifySign(String content, String sign, String publicKeyStr) {
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);

        try {
            byte[] signByte = Base64Util.getByteByDecrypt(sign);

            Signature signature = Signature.getInstance(ALGORITHM_SHA256);
            PublicKey publicKey = getPublicKey(publicKeyStr);
            signature.initVerify(publicKey);
            signature.update(contentByte);
            return signature.verify(signByte);
        } catch (Exception e) {
            e.fillInStackTrace();
        }

        return false;
    }

    /**
     * 获取PublicKey
     */
    private static PublicKey getPublicKey(String publicKeyStr) {
        try {
            byte[] publicKeyByte = Base64Util.getByteByDecrypt(publicKeyStr);

            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}